package com.runfast.waimai.service.impl;

import com.runfast.common.dao.model.RunfastCuser;
import com.runfast.common.dao.model.RunfastDeliverCost;
import com.runfast.common.security.spring.UserDataDetails;
import com.runfast.common.service.BaseService;
import com.runfast.common.service.RunfastDeliverCostService;
import com.runfast.common.utils.DateUtils;
import com.runfast.common.web.entity.Result;
import com.runfast.common.web.entity.ResultCode;
import com.runfast.paotui.entity.DeliveryCost;
import com.runfast.waimai.dao.mapper.RunfastBusinessMapper;
import com.runfast.waimai.dao.model.*;
import com.runfast.waimai.entity.DeliveryRange;
import com.runfast.waimai.service.*;
import com.runfast.waimai.web.dto.ActivityDto;
import com.runfast.waimai.web.dto.BusinessDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class RunfastBusinessServiceImpl extends BaseService<RunfastBusiness, Integer, RunfastBusinessExample> implements RunfastBusinessService {


    @Autowired
    private RunfastActivityService activityService;

    @Autowired
    private RunfastFullLessService fullLessService;

    @Autowired
    private RunfastGoodsSellStandardService goodsSellStandardService;

    @Autowired
    private RunfastDeliverCostService deliverCostService;

    @Autowired
    private RunfastGoodsSellService goodsSellService;

    @Autowired
    private RunfastGoodsSellOptionService optionService;

    @Autowired
    private RunfastEnshrineService enshrineService;


    @Autowired
    private RunfastBusinessHasTypeService businessHasTypeService;

    @Override
    public RunfastBusinessMapper getMapper() {
        return (RunfastBusinessMapper) super.getMapper();
    }

    @Override
    public List<Map<String, Object>> nearBy(Integer agentId, Integer range, Double userLng, Double userLat, Integer sorting, List<Integer> activityType, List<Integer> catalogId, Integer businessFeature, Pageable pageable) {


        log.warn("代理商id： " + agentId);
        Validate.notNull(agentId, "agentId不能为null");
        Validate.notNull(userLng, "userLng不能为null");
        Validate.notNull(userLat, "userLat不能为null");
        Validate.notNull(sorting, "sorting不能为null");

        RunfastDeliverCost defaultDeliveryTemplate = deliverCostService.getDefaultDeliveryTemplate(agentId);
        Date deliveryStart1 = defaultDeliveryTemplate.getStartTimeDay1();
        Date deliveryEnd1 = defaultDeliveryTemplate.getEndTimeDay1();
        Date deliveryStart2 = defaultDeliveryTemplate.getStartTimeNight2();
        Date deliveryEnd2 = defaultDeliveryTemplate.getEndTimeNight2();

        List<BusinessDto> businessDtoList = getMapper().nearBy(agentId, range, userLng, userLat, deliveryStart1, deliveryEnd1, deliveryStart2, deliveryEnd2, sorting, activityType, null, catalogId, businessFeature, pageable);


        List<Map<String, Object>> businessList = new ArrayList<>();
        for (BusinessDto businessDto : businessDtoList) {
            //重新获取全部的活动
            Integer businessId = businessDto.getId();
            List<ActivityDto> activityDtoList = activityService.findBusinessActivityDto(businessId);
            businessDto.setActivityList(activityDtoList);

            businessList.add(detail(null, businessDto));


        }
        return businessList;
    }

    @Override
    public List<Map<String, Object>> offZoneMoreBusiness(Integer agentId, Integer range, Double userLng, Double userLat, List<Integer> activityType, Pageable pageable) {

        Validate.notNull(agentId, "agentId不能为null");
        Validate.notNull(userLng, "userLng不能为null");
        Validate.notNull(userLat, "userLat不能为null");

        RunfastDeliverCost defaultDeliveryTemplate = deliverCostService.getDefaultDeliveryTemplate(agentId);
        Date deliveryStart1 = defaultDeliveryTemplate.getStartTimeDay1();
        Date deliveryEnd1 = defaultDeliveryTemplate.getEndTimeDay1();
        Date deliveryStart2 = defaultDeliveryTemplate.getStartTimeNight2();
        Date deliveryEnd2 = defaultDeliveryTemplate.getEndTimeNight2();

        Integer specialType = 1;
        List<BusinessDto> businessDtoList = getMapper().nearBy(agentId, range, userLng, userLat, deliveryStart1, deliveryEnd1, deliveryStart2, deliveryEnd2, 1, activityType, specialType, null, null, pageable);


        List<Map<String, Object>> businessList = new ArrayList<>();
        for (BusinessDto businessDto : businessDtoList) {
            //重新获取全部的活动
            Integer businessId = businessDto.getId();
            List<ActivityDto> activityDtoList = activityService.findBusinessActivityDto(businessId);
            businessDto.setActivityList(activityDtoList);


            businessList.add(detail(null, businessDto));


        }
        return businessList;
    }

    @Override
    public Result detail(Integer businessId, Double userLng, Double userLat) {
        Validate.notNull(businessId, "agentId不能为null");
        Validate.notNull(userLng, "userLng不能为null");
        Validate.notNull(userLat, "userLat不能为null");

        RunfastBusiness business = getMapper().selectByPrimaryKey(businessId);
        if (business == null) return Result.fail(ResultCode.FAIL, "商家不存在");
        Integer agentId = business.getAgentId();
        RunfastDeliverCost defaultDeliveryTemplate = deliverCostService.getDefaultDeliveryTemplate(agentId);
        Date deliveryStart1 = defaultDeliveryTemplate.getStartTimeDay1();
        Date deliveryEnd1 = defaultDeliveryTemplate.getEndTimeDay1();
        Date deliveryStart2 = defaultDeliveryTemplate.getStartTimeNight2();
        Date deliveryEnd2 = defaultDeliveryTemplate.getEndTimeNight2();
        BusinessDto businessDto = getMapper().detailWithIsOpen(businessId, userLng, userLat, deliveryStart1, deliveryEnd1, deliveryStart2, deliveryEnd2);

        if (businessDto == null) return Result.fail(ResultCode.FAIL, "商家不存在");


        return Result.ok("", detail(defaultDeliveryTemplate, businessDto));

    }

    /**
     * 根据配送模板计算商家信息，获取数据库不能一次性全部取出需要的数据
     *
     * @param defaultDeliveryTemplate 为null,即相关信息已存在，不需要重复计算
     * @param businessDto
     * @return
     */
    @Override
    public Map<String, Object> detail(RunfastDeliverCost defaultDeliveryTemplate, BusinessDto businessDto) {

        /**
         *是否是新商户
         */


        Map<String, Object> businessMap = new HashMap<>();
        businessMap.putAll(BeanMap.create(businessDto));
        businessMap.put("newBusiness", false);
        if (businessDto.getCreateTime() != null) {
            Date date = new Date();
            Date createTime = (Date) businessDto.getCreateTime();
            long aa = createTime.getTime() + 864000000;
            if (date.getTime() < aa) {
                businessMap.put("newBusiness", true);
            }

        }

        businessMap.put("enshrined", false);

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication instanceof AnonymousAuthenticationToken)) {
            UserDataDetails<RunfastCuser> principal = (UserDataDetails<RunfastCuser>) authentication.getPrincipal();
            RunfastCuser cuser = principal.getData();


            /**
             * 是否被收藏
             */
            RunfastEnshrineExample enshrineExample = new RunfastEnshrineExample();
            enshrineExample.or().andCidEqualTo(cuser.getId()).andTypeEqualTo(1).andShopIdEqualTo(businessDto.getId());

            long count = enshrineService.countByExample(enshrineExample);

            if (count > 0) businessMap.put("enshrined", true);
        }


        if (StringUtils.isNotBlank(businessDto.getImgPath())) {

            String mini_imgPath = businessDto.getMini_imgPath();
            if (StringUtils.isBlank(mini_imgPath)) {
                businessMap.put("mini_imgPath", businessDto.getImgPath());
            }
        }
        //获取商家配送信息
        Map<String, Object> deliveryInfo = getDeliveryInfo(businessDto);
        businessMap.putAll(deliveryInfo);

        /**
         * 计算当前商家参与的活动
         */
        List<ActivityDto> activityList = businessDto.getActivityList();

        //活动类型：1满减  2打折3赠品4特价5满减免运费6优惠券7免部分配送费8新用户立减活动9首单立减活动10商户红包11下单返红包
        for (ActivityDto activity : activityList) {
            Integer ptype = activity.getPtype();
            switch(ptype){
                case 1:{
                    Integer activityId = activity.getId();

                    RunfastFullLessExample fullLessExample = new RunfastFullLessExample();
                    fullLessExample.or().andActivity_idEqualTo(activityId);
                    fullLessExample.setOrderByClause("full asc");
                    List<RunfastFullLess> fullLessList = fullLessService.selectByExampleWithPageable(fullLessExample, PageRequest.of(0, 5));
                    activity.setFullLessList(fullLessList);
                    break;
                }
                case 5:
                case 7:
                    Double fulls = activity.getFulls();
                    fulls = fulls ==null?0D:fulls;
                    System.out.println("========"+fulls+"=======");
                    if (fulls==0D) { //无门槛
                        businessMap.put("deliveryFee",BigDecimal.valueOf(0));
                    }
                    break;
            }


        }





        /**
         * 是否计算商家营业状态
         */
        if (defaultDeliveryTemplate != null) {
            String weekday = (String) businessDto.getWorktoday();

            Date businessStart1 = (Date) businessDto.getStartwork();
            Date businessEnd1 = (Date) businessDto.getEndwork();
            Date businessStart2 = (Date) businessDto.getStartwork2();
            Date businessEnd2 = (Date) businessDto.getEndwork2();

            Date deliveryStart1 = defaultDeliveryTemplate.getStartTimeDay1();
            Date deliveryEnd1 = defaultDeliveryTemplate.getEndTimeDay1();
            Double cost1 = defaultDeliveryTemplate.getTimeCost1();
            BigDecimal timeCost1 = cost1 == null ? BigDecimal.valueOf(0) : BigDecimal.valueOf(cost1);

            Date deliveryStart2 = defaultDeliveryTemplate.getStartTimeNight2();
            Date deliveryEnd2 = defaultDeliveryTemplate.getEndTimeNight2();
            Double cost2 = defaultDeliveryTemplate.getTimeCost2();
            BigDecimal timeCost2 = cost2 == null ? BigDecimal.valueOf(0) : BigDecimal.valueOf(cost2);

            Integer deliver = (Integer) businessDto.getIsDeliver();
            boolean isDeliver = deliver != null && deliver == 1;


            Integer status = (Integer) businessDto.getStatus();//后台设置商家营业状态
            Integer statu = (Integer) businessDto.getStatu();//商家设置营业状态

            List<DeliveryRange> deliveryRange = DateUtils.getDeliveryRange(weekday, businessStart1, businessEnd1, businessStart2, businessEnd2, deliveryStart1, deliveryEnd1, deliveryStart2, deliveryEnd2, isDeliver, status, statu, timeCost1, timeCost2);

            businessMap.put("deliveryRange", deliveryRange);
        }


        RunfastBusinessHasTypeExample businessHasTypeExample = new RunfastBusinessHasTypeExample();
        businessHasTypeExample.or().andBusinessIdEqualTo(businessDto.getId()).andTypeEqualTo(0);
        List<RunfastBusinessHasType> businessHasTypeList = businessHasTypeService.selectByExample(businessHasTypeExample);

        businessMap.put("mainTypeId", null);
        if (!businessHasTypeList.isEmpty()) {
            RunfastBusinessHasType businessHasType = businessHasTypeList.get(0);
            businessMap.put("mainTypeId", businessHasType.getSecondId());
        }


        return businessMap;
    }

    /**
     * 获取商家配送信息
     *
     * @param businessDto
     * @return
     */
    @Override
    public Map<String, Object> getDeliveryInfo(BusinessDto businessDto) {
        /**
         * 计算商家配送费和配送时间
         */
        Double distance = businessDto.getDistance();//以米为单位
        Integer deliver = (Integer) businessDto.getIsDeliver();
        boolean isDeliver = deliver != null && deliver == 1;

        RunfastDeliverCost defaultDeliveryTemplate = deliverCostService.getDefaultDeliveryTemplate(businessDto.getAgentId());

        int deliveryDuration = 0;//配送时间（分）
        BigDecimal deliveryFee = BigDecimal.valueOf(0);//配送费
        if (isDeliver) {
            //自配送

            BigDecimal busshowps = (BigDecimal) businessDto.getBusshowps();
            if (busshowps == null || busshowps.compareTo(BigDecimal.valueOf(0)) == -1) {
                busshowps = BigDecimal.valueOf(0);
            }
            deliveryFee = busshowps;

            Integer packTime = (Integer) businessDto.getPackTime();
            packTime = packTime == null ? 10 : packTime;
            Integer distributionTime = (Integer) businessDto.getDistributionTime();
            distributionTime = distributionTime == null ? 10 : distributionTime;
            deliveryDuration = packTime + distributionTime;

        } else {
            distance = (distance == null ? 0d : distance);
            //代理商配送
            DeliveryCost deliveryCost = deliverCostService.getDeliveryCost(distance.intValue(), null, defaultDeliveryTemplate);

            deliveryFee = BigDecimal.valueOf(deliveryCost.getDeliveryFee()).divide(BigDecimal.valueOf(100), 2);

            Double speed = defaultDeliveryTemplate.getSpeed();
            int distributionTime = (int) Math.ceil(distance * 10 * speed / 1000);
            Integer packTime = (Integer) businessDto.getPackTime();
            packTime = packTime == null ? 10 : packTime;
            deliveryDuration = packTime + distributionTime;
            deliveryDuration = deliveryDuration < 25 ? 25 : deliveryDuration;//少于25分钟按照25分钟计算
        }
        Map<String, Object> businessMap = new HashMap<>();
        businessMap.put("deliveryFee", deliveryFee);
        businessMap.put("deliveryDuration", deliveryDuration);
        return businessMap;
    }

    /**
     * 每种活动类型，只保留第一个活动
     *
     * @param activityTypeMap
     * @param activity
     * @param activityType
     * @return
     */
    private ActivityDto putActivityIfNotExist(HashMap<String, ActivityDto> activityTypeMap, ActivityDto activity, String activityType) {
        ActivityDto activityDto = activityTypeMap.get(activityType);
        if (activityDto != null) return activityDto;

        activityTypeMap.put(activityType, activity);
        return activity;
    }


    @Override
    public List<Map<String, Object>> search(String name, Integer agentId, Double userLng, Double userLat, Pageable pageable) {

        Validate.notNull(agentId, "name不能为null");
        Validate.notNull(agentId, "agentId不能为null");
        Validate.notNull(agentId, "userLng不能为null");
        Validate.notNull(agentId, "userLat不能为null");

        RunfastDeliverCost defaultDeliveryTemplate = deliverCostService.getDefaultDeliveryTemplate(agentId);
        Date deliveryStart1 = defaultDeliveryTemplate.getStartTimeDay1();
        Date deliveryEnd1 = defaultDeliveryTemplate.getEndTimeDay1();
        Date deliveryStart2 = defaultDeliveryTemplate.getStartTimeNight2();
        Date deliveryEnd2 = defaultDeliveryTemplate.getEndTimeNight2();


        List<BusinessDto> businessDtoList = getMapper().search(name, agentId, userLng, userLat, deliveryStart1, deliveryEnd1, deliveryStart2, deliveryEnd2, pageable);


        List<Map<String, Object>> businessList = new ArrayList<>();
        for (BusinessDto businessDto : businessDtoList) {
            Map<String, Object> detail = detail(null, businessDto);


            RunfastGoodsSellExample goodsSellExample = new RunfastGoodsSellExample();
            goodsSellExample.or().andBusinessIdEqualTo(businessDto.getId()).andStatusEqualTo(0).andNameLike("%" + name + "%");
            goodsSellExample.or().andBusinessIdEqualTo(businessDto.getId()).andStatusIsNull().andNameLike("%" + name + "%");

            List<RunfastGoodsSell> goodsSellList = goodsSellService.search(name, businessDto.getId(), PageRequest.of(0, 5));
            for (RunfastGoodsSell goodsSell : goodsSellList) {
                Integer goodsId = goodsSell.getId();
                List<RunfastGoodsSellOption> goodsSellOptions = optionService.findOptionWithSub(goodsId);

                goodsSell.setGoodsSellOptionList(goodsSellOptions);
            }
            detail.put("goodsSellList", goodsSellList);
            businessList.add(detail);
        }
        return businessList;
    }

    /**
     * 获取代理商下专区商家列表
     *
     * @param activityId
     * @param pageable
     * @return
     */
    @Override
    public Result getAgentZoneBusiness(Integer activityId, Double userLng, Double userLat, Pageable pageable) {
        List<Integer> businessIdList = new ArrayList<>();
        ;
        RunfastActivity activityWithTarget = activityService.getActivityWithTarget(activityId, pageable);
        if (activityWithTarget == null) return Result.ok("");
        List<RunfastActivityTarget> activityTargetList = activityWithTarget.getActivityTargetList();
        Integer agentId = null;

        for (RunfastActivityTarget activityTarget : activityTargetList) {
            agentId = activityTarget.getAgentId();
            Integer businessId = activityTarget.getBusinessId();
            businessIdList.add(businessId);
        }


        RunfastDeliverCost defaultDeliveryTemplate = deliverCostService.getDefaultDeliveryTemplate(agentId);

        Date deliveryStart1 = defaultDeliveryTemplate.getStartTimeDay1();
        Date deliveryEnd1 = defaultDeliveryTemplate.getEndTimeDay1();
        Date deliveryStart2 = defaultDeliveryTemplate.getStartTimeNight2();
        Date deliveryEnd2 = defaultDeliveryTemplate.getEndTimeNight2();
        List<BusinessDto> businessDtoList = getMapper().listBusinessIsOpen(businessIdList, userLng, userLat, deliveryStart1, deliveryEnd1, deliveryStart2, deliveryEnd2);

        List<Map<String, Object>> businessList = new ArrayList<>();
        for (BusinessDto businessDto : businessDtoList) {
            businessList.add(detail(null, businessDto));
        }
        return Result.ok("", businessList);

    }

    @Override
    public BusinessDto detailWithDistance(Integer businessId, Double toLng, Double toLat) {
        return getMapper().detailWithDistance(businessId, toLng, toLat);
    }

    @Override
    public BusinessDto detailWithIsOpen(Integer businessId, Double toLng, Double toLat, Date deliveryStart1, Date deliveryEnd1, Date deliveryStart2, Date deliveryEnd2) {
        return getMapper().detailWithIsOpen(businessId, toLng, toLat, deliveryStart1, deliveryEnd1, deliveryStart2, deliveryEnd2);
    }

    @Override
    public Map<String, Object> findNameById(Integer businessId) {
        return getMapper().findNameById(businessId);
    }

    @Override
    public Map<String, Object> findImgById(Integer businessId) {
        return getMapper().findImgById(businessId);
    }


}